package com.xjrsoft.module.login.controller;

import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.xjrsoft.common.config.JPushConfig;
import com.xjrsoft.common.config.WxConfig;
import com.xjrsoft.common.result.Response;
import com.xjrsoft.common.result.ResultCode;
import com.xjrsoft.common.utils.RedisUtil;
import com.xjrsoft.core.constant.RedisKeyConstants;
import com.xjrsoft.core.log.annotation.ApiLog;
import com.xjrsoft.core.tool.utils.*;
import com.xjrsoft.module.base.entity.XjrBaseCompany;
import com.xjrsoft.module.base.entity.XjrBaseDepartment;
import com.xjrsoft.module.base.entity.XjrBaseRole;
import com.xjrsoft.module.base.entity.XjrBaseUser;
import com.xjrsoft.module.base.service.IXjrBaseCompanyService;
import com.xjrsoft.module.base.service.IXjrBaseUserService;
import com.xjrsoft.module.base.vo.CompanyPageListVo;
import com.xjrsoft.module.base.vo.DepartmentTreeVo;
import com.xjrsoft.module.base.vo.RoleVo;
import com.xjrsoft.module.login.dto.LoginInfoDto;
import com.xjrsoft.module.login.dto.WxLoginInfoDto;
import com.xjrsoft.module.login.entity.WxLoginResult;
import com.xjrsoft.module.login.utils.SmsKit;
import com.xjrsoft.module.login.vo.LoginSuccessVo;
import com.xjrsoft.module.login.vo.UserInfoVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.stream.Collectors;

@RestController
@AllArgsConstructor
@RequestMapping("/login")
@Api(value = "用户登录", tags = "登录接口")
@Slf4j
public class LoginController {

	private RedisUtil redisUtil;

	private IXjrBaseUserService userService;

	private IXjrBaseCompanyService companyService;


	@ApiLog("登录")
	@PostMapping
	@ApiOperation(value = "登录获取token", notes = "传入账号:account,密码:password")
	public Response<LoginSuccessVo> login(@RequestBody LoginInfoDto loginInfoDto) {
		String account = loginInfoDto.getAccount();
		String password = loginInfoDto.getPassword();

		XjrBaseUser user = userService.userInfo(account, password);

		if (user == null) {
			return Response.notOk("帐号密码错误！");
		} else if (!Integer.valueOf(1).equals(user.getEnabledMark())) {
			return Response.notOk("该账号已被禁用！");
		}

		//此登录接口登录web端
		StpUtil.login(user.getUserId(), loginInfoDto.getDevice());
		SaSession tokenSession = StpUtil.getTokenSession();
		tokenSession.set("user", user);


		List<XjrBaseDepartment> departments = userService.queryDepartmentsOfUser(user.getUserId());
		XjrBaseCompany companies = companyService.getById(user.getCompanyId());
		List<XjrBaseRole> role = userService.queryRolesOfUser(user.getUserId());


		// 设置返回数据
		UserInfoVo userInfoVo = BeanUtil.copy(user, UserInfoVo.class);

		if (companies != null) {
			userInfoVo.setCompany(BeanUtil.copy(companies, CompanyPageListVo.class));

			tokenSession.set("company", companyService.getById(user.getCompanyId()));
		}

		if (departments != null) {
			userInfoVo.setDepartments(BeanUtil.copyList(departments, DepartmentTreeVo.class));
			tokenSession.set("dept", userService.queryDepartmentsOfUser(user.getUserId()));

		}

		if (role != null) {
			userInfoVo.setRoles(BeanUtil.copyList(role, RoleVo.class));
			tokenSession.set(RedisKeyConstants.CACHE_ROLE_CODE_KEY, role.stream().map(XjrBaseRole::getEnCode).collect(Collectors.toList()));
			tokenSession.set("role", userService.queryRolesOfUser(user.getUserId()));
		}


		LoginSuccessVo loginVo = new LoginSuccessVo();
		loginVo.setUserInfoVo(userInfoVo);
		loginVo.setToken(StpUtil.getTokenValue());


		//移动端登录保存用户移动设备的id
		String registrationId = loginInfoDto.getRegistrationId();
		if (StringUtil.equals(loginInfoDto.getDevice(), "app") && StringUtil.isNotBlank(registrationId)) {
			XjrBaseUser xjrBaseUser = userService.getOne(Wrappers.<XjrBaseUser>query().lambda().eq(XjrBaseUser::getRegistrationId, registrationId));
			if (xjrBaseUser != null && !StringUtil.equals(xjrBaseUser.getUserId(), user.getUserId())) {
				xjrBaseUser.setRegistrationId("");
				userService.updateById(xjrBaseUser);
			}
			user.setRegistrationId(loginInfoDto.getRegistrationId());
			userService.updateById(user);
		}
		return Response.ok(loginVo, "登录成功！");
	}


	@ApiLog("登出")
	@PostMapping("/logout")
	public Response logout() {
		if (StpUtil.isLogin()) {
			String loginDevice = StpUtil.getLoginDevice();
			Object loginId = StpUtil.getLoginId();
			if (StringUtil.equals(loginDevice, "app") && loginId != null) {
				//移动端退出登录时,删除设备id
				String id = String.valueOf(loginId);
				XjrBaseUser xjrBaseUser = userService.getById(id);
				if (xjrBaseUser != null) {
					xjrBaseUser.setRegistrationId("");
					userService.updateById(xjrBaseUser);
				}
			}

			if (StringUtil.equals(loginDevice, "wx") && loginId != null) {
				//移动端退出登录时,删除设备id
				String id = String.valueOf(loginId);
				XjrBaseUser xjrBaseUser = userService.getById(id);
				if (xjrBaseUser != null) {
					xjrBaseUser.setWeChat("");
					userService.updateById(xjrBaseUser);
				}
			}
			StpUtil.logout();
		}
		return Response.ok();
	}

	@ApiLog("验证码登录")
	@PostMapping("/phone")
	@ApiOperation(value = "验证码登录获取token", notes = "传入手机号:account, 验证码:password")
	public Response loginOnline(@RequestBody LoginInfoDto loginInfoDto) {
		String mobile = loginInfoDto.getAccount();
		if (!SmsKit.isPhone(mobile)) {
			return Response.notOk("手机号错误！");
		}
		if (redisUtil.getExpire(RedisKeyConstants.CACHE_SMS_CODE_PREFIX + mobile) > System.currentTimeMillis()) {
			return Response.notOk("验证码已过期！");
		}
		String cacheSmsCode = Func.toStr(redisUtil.get(RedisKeyConstants.CACHE_SMS_CODE_PREFIX + mobile));
		if (!StringUtil.equals(cacheSmsCode, loginInfoDto.getPassword())) {
			return Response.notOk("验证码错误！");
		}
		//移动端登录保存用户移动设备的id
		String registrationId = loginInfoDto.getRegistrationId();
		XjrBaseUser user = userService.getOne(Wrappers.<XjrBaseUser>query().lambda().eq(XjrBaseUser::getMobile, mobile));
		if (user != null && StringUtil.equals(loginInfoDto.getDevice(), "app") && StringUtil.isNotBlank(registrationId)) {
			XjrBaseUser xjrBaseUser = userService.getOne(Wrappers.<XjrBaseUser>query().lambda().eq(XjrBaseUser::getRegistrationId, registrationId));
			if (xjrBaseUser != null && !StringUtil.equals(xjrBaseUser.getUserId(), user.getUserId())) {
				xjrBaseUser.setRegistrationId("");
				userService.updateById(xjrBaseUser);
			}
			user.setRegistrationId(loginInfoDto.getRegistrationId());
			userService.updateById(user);
		}
		return login(loginInfoDto);
	}

	@GetMapping("/{mobile}")
	@ApiOperation(value = "发送验证码")
	public Response sendSms(@PathVariable String mobile) {
		String smsCode = StringPool.EMPTY;

		if (SmsKit.isPhone(mobile)) {
			try {
				smsCode = SmsKit.sendSmsByHuaWei(mobile);
			} catch (Exception e) {
				log.error("发送短信失败！", e);
				return Response.notOk("发送短信失败！");
			}
		}
		Integer count = userService.count(Wrappers.<XjrBaseUser>query().lambda().eq(XjrBaseUser::getMobile, mobile));
		if (count == 0) {
			// 保存手机号码
			XjrBaseUser user = new XjrBaseUser();
			user.setMobile(mobile);
			userService.save(user);
		}
		if (StringUtil.isNotBlank(smsCode)) {
			redisUtil.set(RedisKeyConstants.CACHE_SMS_CODE_PREFIX + mobile, smsCode, 600);
			return Response.status(true);
		}
		return Response.status(false);
	}

	@PostMapping("/add-clue")
	@ApiOperation(value = "crm增加数据")
	public Response addClue() {
		return null;
	}

	@ApiLog("微信登录")
	@PostMapping("/wechat")
	@ApiOperation(value = "微信登录", notes = "传入微信授权code")
	public Response<LoginSuccessVo> wxLogin(@RequestBody WxLoginInfoDto dto) {

		//如果使用授权码登录
		if(StrUtil.isNotBlank(dto.getCode())){
			String code = dto.getCode();

			WxConfig wxConfig = SpringUtil.getBean(WxConfig.class);

			String result = HttpUtil.get("https://api.weixin.qq.com/sns/jscode2session?appid=" + wxConfig.getAppid() + "&secret=" + wxConfig.getAppsecret() + "&js_code=" + code + "&grant_type=authorization_code");

			WxLoginResult wxLoginResult = JSONUtil.toBean(result, WxLoginResult.class);

			//如果成功
			if(wxLoginResult.getErrcode() ==null|| wxLoginResult.getErrcode() == 0){
				XjrBaseUser user = userService.getOne(Wrappers.<XjrBaseUser>query().lambda().eq(XjrBaseUser::getWeChat, wxLoginResult.getOpenid()));

				if (user == null) {
					return Response.notOk(ResultCode.WX_LOGIN_ERROR.getCode(),wxLoginResult.getOpenid());
				} else if (!Integer.valueOf(1).equals(user.getEnabledMark())) {
					return Response.notOk("该账号已被禁用！");
				}

				//此登录接口登录web端
				StpUtil.login(user.getUserId(), dto.getDevice());
				SaSession tokenSession = StpUtil.getTokenSession();
				tokenSession.set("user", user);


				List<XjrBaseDepartment> departments = userService.queryDepartmentsOfUser(user.getUserId());
				XjrBaseCompany companies = companyService.getById(user.getCompanyId());
				List<XjrBaseRole> role = userService.queryRolesOfUser(user.getUserId());


				// 设置返回数据
				UserInfoVo userInfoVo = BeanUtil.copy(user, UserInfoVo.class);

				if (companies != null) {
					userInfoVo.setCompany(BeanUtil.copy(companies, CompanyPageListVo.class));

					tokenSession.set("company", companyService.getById(user.getCompanyId()));
				}

				if (departments != null) {
					userInfoVo.setDepartments(BeanUtil.copyList(departments, DepartmentTreeVo.class));
					tokenSession.set("dept", userService.queryDepartmentsOfUser(user.getUserId()));

				}

				if (role != null) {
					userInfoVo.setRoles(BeanUtil.copyList(role, RoleVo.class));
					tokenSession.set(RedisKeyConstants.CACHE_ROLE_CODE_KEY, role.stream().map(XjrBaseRole::getEnCode).collect(Collectors.toList()));
					tokenSession.set("role", userService.queryRolesOfUser(user.getUserId()));
				}


				LoginSuccessVo loginVo = new LoginSuccessVo();
				loginVo.setUserInfoVo(userInfoVo);
				loginVo.setToken(StpUtil.getTokenValue());

				//关联微信openid
				user.setWeChat(wxLoginResult.getOpenid());
				userService.updateById(user);

				return Response.ok(loginVo, "登录成功！");
			}
			else{
				return Response.notOk(wxLoginResult.getErrmsg());
			}
		}

		//如果使用账号密码登录
		if(StrUtil.isNotBlank(dto.getOpenId())) {
			XjrBaseUser user = userService.userInfo(dto.getAccount(), dto.getPassword());

			if (user == null) {
				return Response.notOk(ResultCode.WX_LOGIN_ERROR.getCode(),"账号密码错误！");
			} else if (!Integer.valueOf(1).equals(user.getEnabledMark())) {
				return Response.notOk("该账号已被禁用！");
			}

			//此登录接口登录web端
			StpUtil.login(user.getUserId(), dto.getDevice());
			SaSession tokenSession = StpUtil.getTokenSession();
			tokenSession.set("user", user);


			List<XjrBaseDepartment> departments = userService.queryDepartmentsOfUser(user.getUserId());
			XjrBaseCompany companies = companyService.getById(user.getCompanyId());
			List<XjrBaseRole> role = userService.queryRolesOfUser(user.getUserId());


			// 设置返回数据
			UserInfoVo userInfoVo = BeanUtil.copy(user, UserInfoVo.class);

			if (companies != null) {
				userInfoVo.setCompany(BeanUtil.copy(companies, CompanyPageListVo.class));

				tokenSession.set("company", companyService.getById(user.getCompanyId()));
			}

			if (departments != null) {
				userInfoVo.setDepartments(BeanUtil.copyList(departments, DepartmentTreeVo.class));
				tokenSession.set("dept", userService.queryDepartmentsOfUser(user.getUserId()));

			}

			if (role != null) {
				userInfoVo.setRoles(BeanUtil.copyList(role, RoleVo.class));
				tokenSession.set(RedisKeyConstants.CACHE_ROLE_CODE_KEY, role.stream().map(XjrBaseRole::getEnCode).collect(Collectors.toList()));
				tokenSession.set("role", userService.queryRolesOfUser(user.getUserId()));
			}


			LoginSuccessVo loginVo = new LoginSuccessVo();
			loginVo.setUserInfoVo(userInfoVo);
			loginVo.setToken(StpUtil.getTokenValue());

			//关联微信openid
			user.setWeChat(dto.getOpenId());
			userService.updateById(user);

			return Response.ok(loginVo, "登录成功！");
		}

		if(StrUtil.isNotBlank(dto.getSmsCode())){
			String mobile = dto.getAccount();
			if (!SmsKit.isPhone(mobile)) {
				return Response.notOk("手机号错误！");
			}
			if (redisUtil.getExpire(RedisKeyConstants.CACHE_SMS_CODE_PREFIX + mobile) > System.currentTimeMillis()) {
				return Response.notOk("验证码已过期！");
			}
			String cacheSmsCode = Func.toStr(redisUtil.get(RedisKeyConstants.CACHE_SMS_CODE_PREFIX + mobile));
			if (!StringUtil.equals(cacheSmsCode, dto.getPassword())) {
				return Response.notOk("验证码错误！");
			}
			XjrBaseUser user = userService.getOne(Wrappers.<XjrBaseUser>query().lambda().eq(XjrBaseUser::getMobile, mobile));

			if (user == null) {
				return Response.notOk(ResultCode.WX_LOGIN_ERROR.getCode(),"账号密码错误！");
			} else if (!Integer.valueOf(1).equals(user.getEnabledMark())) {
				return Response.notOk("该账号已被禁用！");
			}

			//此登录接口登录web端
			StpUtil.login(user.getUserId(), dto.getDevice());
			SaSession tokenSession = StpUtil.getTokenSession();
			tokenSession.set("user", user);


			List<XjrBaseDepartment> departments = userService.queryDepartmentsOfUser(user.getUserId());
			XjrBaseCompany companies = companyService.getById(user.getCompanyId());
			List<XjrBaseRole> role = userService.queryRolesOfUser(user.getUserId());


			// 设置返回数据
			UserInfoVo userInfoVo = BeanUtil.copy(user, UserInfoVo.class);

			if (companies != null) {
				userInfoVo.setCompany(BeanUtil.copy(companies, CompanyPageListVo.class));

				tokenSession.set("company", companyService.getById(user.getCompanyId()));
			}

			if (departments != null) {
				userInfoVo.setDepartments(BeanUtil.copyList(departments, DepartmentTreeVo.class));
				tokenSession.set("dept", userService.queryDepartmentsOfUser(user.getUserId()));

			}

			if (role != null) {
				userInfoVo.setRoles(BeanUtil.copyList(role, RoleVo.class));
				tokenSession.set(RedisKeyConstants.CACHE_ROLE_CODE_KEY, role.stream().map(XjrBaseRole::getEnCode).collect(Collectors.toList()));
				tokenSession.set("role", userService.queryRolesOfUser(user.getUserId()));
			}


			LoginSuccessVo loginVo = new LoginSuccessVo();
			loginVo.setUserInfoVo(userInfoVo);
			loginVo.setToken(StpUtil.getTokenValue());

			//关联微信openid
			user.setWeChat(dto.getOpenId());
			userService.updateById(user);

			return Response.ok(loginVo, "登录成功！");
		}


		return Response.notOk("登录未成功！");

	}

}